home *** CD-ROM | disk | FTP | other *** search
/ Beginning Mac Programming / Beginning Mac Programming.bin / Open Me for REALbasic 3 / REALbasic 3.2 / Example Projects / Reusable Classes_Code / String_IO_Manipulation / Base64 / source-> Base64.xs < prev   
Text File  |  1999-01-31  |  5KB  |  215 lines

  1. /* $Id: Base64.xs,v 1.15 1998/12/18 13:16:27 aas Exp $
  2.  
  3. Copyright 1997-1998 Gisle Aas
  4.  
  5. This library is free software; you can redistribute it and/or
  6. modify it under the same terms as Perl itself.
  7.  
  8.  
  9. The tables and some of the code that used to be here was borrowed from
  10. metamail, which comes with this message:
  11.  
  12.   Copyright (c) 1991 Bell Communications Research, Inc. (Bellcore)
  13.  
  14.   Permission to use, copy, modify, and distribute this material 
  15.   for any purpose and without fee is hereby granted, provided 
  16.   that the above copyright notice and this permission notice 
  17.   appear in all copies, and that the name of Bellcore not be 
  18.   used in advertising or publicity pertaining to this 
  19.   material without the specific, prior written permission 
  20.   of an authorized representative of Bellcore.    BELLCORE 
  21.   MAKES NO REPRESENTATIONS ABOUT THE ACCURACY OR SUITABILITY 
  22.   OF THIS MATERIAL FOR ANY PURPOSE.  IT IS PROVIDED "AS IS", 
  23.   WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
  24.  
  25. */
  26.  
  27.  
  28. #ifdef __cplusplus
  29. extern "C" {
  30. #endif
  31. #include "EXTERN.h"
  32. #include "perl.h"
  33. #include "XSUB.h"
  34. #ifdef __cplusplus
  35. }
  36. #endif
  37.  
  38. #include "patchlevel.h"
  39. #if PATCHLEVEL <= 3 || (PATCHLEVEL == 4 && SUBVERSION <= 4)
  40.    #define PL_dowarn dowarn
  41. #endif
  42.  
  43. #define MAX_LINE  76 /* size of encoded lines */
  44.  
  45. static char basis_64[] =
  46.    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  47.  
  48. #define XX      255    /* illegal base64 char */
  49. #define EQ      254    /* padding */
  50. #define INVALID XX
  51.  
  52. static unsigned char index_64[256] = {
  53.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  54.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  55.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,62, XX,XX,XX,63,
  56.     52,53,54,55, 56,57,58,59, 60,61,XX,XX, XX,EQ,XX,XX,
  57.     XX, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
  58.     15,16,17,18, 19,20,21,22, 23,24,25,XX, XX,XX,XX,XX,
  59.     XX,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
  60.     41,42,43,44, 45,46,47,48, 49,50,51,XX, XX,XX,XX,XX,
  61.  
  62.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  63.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  64.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  65.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  66.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  67.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  68.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  69.     XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
  70. };
  71.  
  72.  
  73.  
  74. MODULE = MIME::Base64        PACKAGE = MIME::Base64
  75.  
  76. SV*
  77. encode_base64(sv,...)
  78.     SV* sv
  79.     PROTOTYPE: $;$
  80.  
  81.     PREINIT:
  82.     char *str;     /* string to encode */
  83.     SSize_t len;   /* length of the string */
  84.     char *eol;     /* the end-of-line sequence to use */
  85.     STRLEN eollen; /* length of the EOL sequence */
  86.     char *r;       /* result string */
  87.     STRLEN rlen;   /* length of result string */
  88.     unsigned char c1, c2, c3;
  89.     int chunk;
  90.  
  91.     CODE:
  92.     str = SvPV(sv, rlen); /* SvPV(sv, len) gives warning for signed len */
  93.     len = (SSize_t)rlen;
  94.  
  95.     /* set up EOL from the second argument if present, default to "\n" */
  96.     if (items > 1 && SvOK(ST(1))) {
  97.         eol = SvPV(ST(1), eollen);
  98.     } else {
  99.         eol = "\n";
  100.         eollen = 1;
  101.     }
  102.  
  103.     /* calculate the length of the result */
  104.     rlen = (len+2) / 3 * 4;     /* encoded bytes */
  105.     if (rlen) {
  106.         /* add space for EOL */
  107.         rlen += ((rlen-1) / MAX_LINE + 1) * eollen;
  108.     }
  109.  
  110.     /* allocate a result buffer */
  111.     RETVAL = newSV(rlen ? rlen : 1);
  112.     SvPOK_on(RETVAL);    
  113.     SvCUR_set(RETVAL, rlen);
  114.     r = SvPVX(RETVAL);
  115.  
  116.     /* encode */
  117.     for (chunk=0; len > 0; len -= 3, chunk++) {
  118.         if (chunk == (MAX_LINE/4)) {
  119.         char *c = eol;
  120.         char *e = eol + eollen;
  121.         while (c < e)
  122.             *r++ = *c++;
  123.         chunk = 0;
  124.         }
  125.         c1 = *str++;
  126.         c2 = *str++;
  127.         *r++ = basis_64[c1>>2];
  128.         *r++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
  129.         if (len > 2) {
  130.         c3 = *str++;
  131.         *r++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
  132.         *r++ = basis_64[c3 & 0x3F];
  133.         } else if (len == 2) {
  134.         *r++ = basis_64[(c2 & 0xF) << 2];
  135.         *r++ = '=';
  136.         } else { /* len == 1 */
  137.         *r++ = '=';
  138.         *r++ = '=';
  139.         }
  140.     }
  141.     if (rlen) {
  142.         /* append eol to the result string */
  143.         char *c = eol;
  144.         char *e = eol + eollen;
  145.         while (c < e)
  146.         *r++ = *c++;
  147.     }
  148.     *r = '\0';  /* every SV in perl should be NUL-terminated */
  149.  
  150.     OUTPUT:
  151.     RETVAL
  152.  
  153. SV*
  154. decode_base64(sv)
  155.     SV* sv
  156.     PROTOTYPE: $
  157.  
  158.     PREINIT:
  159.     STRLEN len;
  160.     register unsigned char *str = (unsigned char*)SvPV(sv, len);
  161.     unsigned char const* end = str + len;
  162.     char *r;
  163.     unsigned char c[4];
  164.  
  165.     CODE:
  166.     {
  167.         /* always enough, but might be too much */
  168.         STRLEN rlen = len * 3 / 4;
  169.         RETVAL = newSV(rlen ? rlen : 1);
  170.     }
  171.         SvPOK_on(RETVAL);
  172.         r = SvPVX(RETVAL);
  173.  
  174.     while (str < end) {
  175.         int i = 0;
  176.             do {
  177.         unsigned char uc = index_64[*str++];
  178.         if (uc != INVALID)
  179.             c[i++] = uc;
  180.  
  181.         if (str == end) {
  182.             if (i < 4) {
  183.             if (PL_dowarn) warn("Premature end of base64 data");
  184.             if (i < 2) goto thats_it;
  185.             if (i == 2) c[2] = EQ;
  186.             c[3] = EQ;
  187.             }
  188.             break;
  189.         }
  190.             } while (i < 4);
  191.         
  192.         if (c[0] == EQ || c[1] == EQ) {
  193.         if (PL_dowarn) warn("Premature padding of base64 data");
  194.         break;
  195.             }
  196.         /* printf("c0=%d,c1=%d,c2=%d,c3=%d\n", c[0],c[1],c[2],c[3]);/**/
  197.  
  198.         *r++ = (c[0] << 2) | ((c[1] & 0x30) >> 4);
  199.  
  200.         if (c[2] == EQ)
  201.         break;
  202.         *r++ = ((c[1] & 0x0F) << 4) | ((c[2] & 0x3C) >> 2);
  203.  
  204.         if (c[3] == EQ)
  205.         break;
  206.         *r++ = ((c[2] & 0x03) << 6) | c[3];
  207.     }
  208.  
  209.       thats_it:
  210.     SvCUR_set(RETVAL, r - SvPVX(RETVAL));
  211.     *r = '\0';
  212.  
  213.     OUTPUT:
  214.     RETVAL
  215.